package cn.turboinfo.dongying.api.provider.common.service.impl.dictconfig;

import cn.turboinfo.dongying.api.domain.common.service.dictconfig.DictConfigItemService;
import cn.turboinfo.dongying.api.domain.common.service.dictconfig.DictConfigService;
import cn.turboinfo.dongying.api.entity.common.exception.dictconfig.DictConfigException;
import cn.turboinfo.dongying.api.entity.common.pojo.dictconfig.DictConfig;
import cn.turboinfo.dongying.api.entity.common.pojo.dictconfig.DictConfigCreator;
import cn.turboinfo.dongying.api.entity.common.pojo.dictconfig.DictConfigUpdater;
import cn.turboinfo.dongying.api.provider.common.repository.database.dictconfig.DictConfigDAO;
import cn.turboinfo.dongying.api.provider.common.repository.database.dictconfig.DictConfigPO;
import lombok.RequiredArgsConstructor;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanUpdaterHelper;
import net.sunshow.toolkit.core.qbean.helper.service.impl.AbstractQServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

@RequiredArgsConstructor
@Service
public class DictConfigServiceImpl extends AbstractQServiceImpl<DictConfig> implements DictConfigService {
    private final DictConfigDAO dictConfigDAO;

    private final DictConfigItemService dictConfigItemService;

    @Override
    public Optional<DictConfig> getById(Long id) {
        return dictConfigDAO.findById(id).map(this::convertQBean);
    }

    @Override
    public DictConfig getByIdEnsure(Long id) {
        return getById(id).orElseThrow(this.getExceptionSupplier("未找到数据, id=" + id, null));
    }

    @Override
    public List<DictConfig> findByIdCollection(Collection<Long> idCollection) {
        return convertStreamQBeanToList(dictConfigDAO.findByIdInOrderByIdDesc(idCollection).stream());
    }

    @Override
    @Transactional
    public DictConfig save(DictConfigCreator creator) throws DictConfigException {
        // 检测字典 Key 是否重复
        if (StringUtils.isNotEmpty(creator.getDictKey())) {
            if (dictConfigDAO.findByDictKey(creator.getDictKey()).isPresent()) {
                throw getExceptionSupplier("字典 Key 已存在", null).get();
            }
        }

        DictConfigPO dictConfigPO = new DictConfigPO();

        QBeanCreatorHelper.copyCreatorField(dictConfigPO, creator);

        return convertQBean(dictConfigDAO.save(dictConfigPO));
    }

    @Override
    @Transactional
    public DictConfig update(DictConfigUpdater updater) throws DictConfigException {
        DictConfigPO dictConfigPO = getEntityWithNullCheckForUpdate(updater.getUpdateId(), dictConfigDAO);

        // 检测字典 Key 是否重复
        if (StringUtils.isNotEmpty(updater.getDictKey()) && !updater.getDictKey().equals(dictConfigPO.getDictKey())) {
            if (dictConfigDAO.findByDictKey(updater.getDictKey()).isPresent()) {
                throw getExceptionSupplier("字典 Key 已存在", null).get();
            }

            // 维护更新子项里面冗余的字典 Key
            dictConfigItemService.updateDictConfigKey(dictConfigPO.getId(), updater.getDictKey());
        }

        QBeanUpdaterHelper.copyUpdaterField(dictConfigPO, updater);

        return convertQBean(dictConfigPO);
    }

    @Override
    public QResponse<DictConfig> searchList(QRequest request, QPage requestPage) {
        return convertQResponse(findAllInternal(request, requestPage));
    }

    private Page<DictConfigPO> findAllInternal(QRequest request, QPage requestPage) {
        return dictConfigDAO.findAll(convertSpecification(request), convertPageable(requestPage));
    }

    @Override
    @Transactional
    public void deleteById(Long id) throws DictConfigException {
        DictConfigPO dictConfigPO = getEntityWithNullCheckForUpdate(id, dictConfigDAO);
        dictConfigDAO.delete(dictConfigPO);
    }

    @Override
    public Optional<DictConfig> getByDictKey(String dictKey) {
        return dictConfigDAO.findByDictKey(dictKey).map(this::convertQBean);
    }

    @Override
    public DictConfig getByDictKeyEnsure(String dictKey) {
        return getByDictKey(dictKey).orElseThrow(this.getExceptionSupplier("未找到数据, dictKey=" + dictKey, null));
    }

    @Override
    protected Supplier<? extends RuntimeException> getExceptionSupplier(String message,
                                                                        Throwable cause) {
        return () -> new DictConfigException(message, cause);
    }
}
